﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;
using Workflows.Components.TextMining.Properties;

namespace Workflows.Components.TextMining.Clustering
{
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class DocumentTermListComponent:WorkflowComponentBase
    {
        #region props

        private DocumentTermListInstruction _Instruction;
        public override InstructionBase Instruction
        {
            get { return _Instruction; }
            set { _Instruction=(DocumentTermListInstruction)value; }
        }

        private DocumentTermListOutput _Output;
        public override ResultBase Output
        {
            get { return _Output; }
            set { _Output=(DocumentTermListOutput)value; }
        }

        /// <summary></summary>
        public string ConnectionString
        {
            get
            {
                return this._Instruction.ConnectionString;
            }
            set
            {
                this._Instruction.ConnectionString = value;
            }
        }

        /// <summary></summary>
        public string SelectSqlStatement
        {
            get
            {
                return this._Instruction.SelectSqlStatement;
            }
            set
            {
                this._Instruction.SelectSqlStatement = value;
            }
        }

        /// <summary></summary>
        public string DocIDField
        {
            get
            {
                return this._Instruction.DocIDField;
            }
            set
            {
                this._Instruction.DocIDField = value;
            }
        }

        /// <summary></summary>
        public string TermIDField
        {
            get
            {
                return this._Instruction.TermIDField;
            }
            set
            {
                this._Instruction.TermIDField = value;
            }
        }

        /// <summary></summary>
        public string TermField
        {
            get
            {
                return this._Instruction.TermField;
            }
            set
            {
                this._Instruction.TermField = value;
            }
        }

        /// <summary></summary>
        public string TermWeightField
        {
            get
            {
                return this._Instruction.TermWeightField;
            }
            set
            {
                this._Instruction.TermWeightField = value;
            }
        }

        /// <summary></summary>
        public string DocLabelField
        {
            get
            {
                return this._Instruction.DocLabelField;
            }
            set
            {
                this._Instruction.DocLabelField = value;
            }
        }

        /// <summary></summary>
        public string DocContentField
        {
            get
            {
                return this._Instruction.DocContentField;
            }
            set
            {
                this._Instruction.DocContentField = value;
            }
        }


        /// <summary>
        /// <Docs>
        ///     <Doc DocID="0" FilePath=""/>
        /// </Docs>
        /// </summary>
        public string DocTermListResultFilePath
        {
            get
            {
                return this._Instruction.DocTermListResultFilePath;
            }
            set
            {
                this._Instruction.DocTermListResultFilePath = value;
            }
        }

        /// <summary></summary>
        public List<string> ExcludedTerms
        {
            get
            {
                return this._Instruction.ExcludedTerms;
            }
            set
            {
                this._Instruction.ExcludedTerms = value;
            }
        }

        /// <summary></summary>
        public bool TermWeightHasCeiling
        {
            get
            {
                return this._Instruction.TermWeightHasCeiling;
            }
            set
            {
                this._Instruction.TermWeightHasCeiling = value;
            }
        }

        /// <summary></summary>
        public bool TermWeightHasFloor
        {
            get
            {
                return this._Instruction.TermWeightHasFloor;
            }
            set
            {
                this._Instruction.TermWeightHasFloor = value;
            }
        }

        /// <summary></summary>
        public bool TermWeightHasExclusion
        {
            get
            {
                return this._Instruction.TermWeightHasExclusion;
            }
            set
            {
                this._Instruction.TermWeightHasExclusion = value;
            }
        }

        /// <summary></summary>
        public double MinTermWeight
        {
            get
            {
                return this._Instruction.MinTermWeight;
            }
            set
            {
                this._Instruction.MinTermWeight = value;
            }
        }

        /// <summary></summary>
        public double MaxTermWeight
        {
            get
            {
                return this._Instruction.MaxTermWeight;
            }
            set
            {
                this._Instruction.MaxTermWeight = value;
            }
        }

        /// <summary></summary>
        public double ExcludedTermWeight
        {
            get
            {
                return this._Instruction.ExcludedTermWeight;
            }
            set
            {
                this._Instruction.ExcludedTermWeight = value;
            }
        }

        /// <summary></summary>
        public string ApplListFilePath
        {
            get
            {
                return this._Instruction.ApplListFilePath;
            }
            set
            {
                this._Instruction.ApplListFilePath = value;
            }
        }

        /// <summary></summary>
        public DataProviderType DbProvider
        {
            get
            {
                return this._Instruction.DbProvider;
            }
            set
            {
                this._Instruction.DbProvider = value;
            }
        }
        #endregion

        #region ctor
        /// <summary>
        /// 
        /// </summary>
        public DocumentTermListComponent():base()
        {
            this.ComponentActivityType = WorkflowActivityType.SimpleActivity;
            this.ComponentCategory = WorkflowComponentCategory.TextMining.ToString();
            this.ComponentIcon = Resources.DfrgRes_106;
            this.ComponentImage = Resources.defrag;
            this.ComponentName = "Document Term List Provider";
            this.Description = "Provide an xml with doc id and associated terms";

            this._Instruction = new DocumentTermListInstruction(
                this.ComponentID, Guid.Empty,
                string.Empty, string.Empty,
                string.Empty, string.Empty,
                string.Empty, string.Empty,
                string.Empty, string.Empty, 
                string.Empty, new List<string>(), 
                false, false, false, 0, -100, 100,
                string.Empty, DataProviderType.MSSQL);
            this._Output = new DocumentTermListOutput(
                this.ComponentID, Guid.Empty,
                0, string.Empty);
        }
        #endregion

        public override WorkflowComponentBase Instantiate(XmlNode xNode)
        {
            if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
            {
                DocumentTermListComponent wfComponent = base.Instantiate(xNode) as DocumentTermListComponent;

                wfComponent.ConnectionString = XmlDataUtil.GetAttributeValue(xNode, "ConnStr", "");
                wfComponent.SelectSqlStatement = XmlDataUtil.GetAttributeValue(xNode, "SQL", "");
                wfComponent.DocIDField = XmlDataUtil.GetAttributeValue(xNode, "DocIDField", "");
                wfComponent.TermIDField = XmlDataUtil.GetAttributeValue(xNode, "TermIDField", "");
                wfComponent.TermField = XmlDataUtil.GetAttributeValue(xNode, "TermField", "");
                wfComponent.TermWeightField = XmlDataUtil.GetAttributeValue(xNode, "TermWeightField", "");
                wfComponent.DocLabelField = XmlDataUtil.GetAttributeValue(xNode, "DocLabelField", "");
                wfComponent.DocContentField = XmlDataUtil.GetAttributeValue(xNode, "DocContentField", "");
                wfComponent.DocTermListResultFilePath = XmlDataUtil.GetAttributeValue(xNode, "DocListFilePath", "");

                wfComponent.TermWeightHasExclusion =
                    bool.Parse(XmlDataUtil.GetAttributeValue(xNode, "HasExcludedTermWeight", false.ToString()));
                wfComponent.TermWeightHasCeiling =
                                    bool.Parse(XmlDataUtil.GetAttributeValue(xNode, "HasMaxTermWeight", false.ToString()));
                wfComponent.TermWeightHasFloor =
                    bool.Parse(XmlDataUtil.GetAttributeValue(xNode, "HasMinTermWeight", false.ToString()));
                wfComponent.MinTermWeight = double.Parse(XmlDataUtil.GetAttributeValue(xNode, "MinTermWeight", "-100"));
                wfComponent.MaxTermWeight = double.Parse(XmlDataUtil.GetAttributeValue(xNode, "MaxTermWeight", "100"));
                wfComponent.ExcludedTermWeight = double.Parse(XmlDataUtil.GetAttributeValue(xNode, "ExcludedTermWeight", "0"));

                wfComponent.ApplListFilePath = XmlDataUtil.GetAttributeValue(xNode, "ApplListFilePath", "");
                wfComponent.DbProvider =
                    (DataProviderType)
                    int.Parse(XmlDataUtil.GetAttributeValue(xNode, "DbProvider",
                                                            ((int)DataProviderType.MSSQL).ToString()));

                XmlNodeList excludedTermNodes = xNode.SelectNodes("ExcludedTerms/ExcludedTerm");
                if (excludedTermNodes != null && excludedTermNodes.Count > 0)
                {
                    wfComponent.ExcludedTerms = new List<string>();
                    foreach (XmlNode excludedTermNode in excludedTermNodes)
                    {
                        wfComponent.ExcludedTerms.Add(XmlDataUtil.GetAttributeValue(excludedTermNode, "Term", ""));
                    }
                }

                return wfComponent;
            }
            else
            {
                throw new Exception("Unable to instantiate component: invalid type specified in xml node");
            }
        }

        public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
        {
            XmlNode xNode = base.Serialize(ref xDoc, ref parentNode);

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ConnStr", this.ConnectionString);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SQL", this.SelectSqlStatement);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "DocIDField", this.DocIDField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TermIDField", this.TermIDField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TermField", this.TermField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode,"TermWeightField",this.TermWeightField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "DocLabelField",this.DocLabelField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "DocContentField", this.DocContentField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "DocListFilePath", this.DocTermListResultFilePath);

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "HasExcludedTermWeight", this.TermWeightHasExclusion.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "HasMinTermWeight", this.TermWeightHasFloor.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "HasMaxTermWeight", this.TermWeightHasCeiling.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ExcludedTermWeight", this.ExcludedTermWeight.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "MinTermWeight", this.MinTermWeight.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "MaxTermWeight", this.MaxTermWeight.ToString());

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ApplListFilePath", this.ApplListFilePath);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "DbProvider", ((int)this.DbProvider).ToString());


            if (this.ExcludedTerms != null && this.ExcludedTerms.Count > 0)
            {
                XmlNode exTermRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "ExcludedTerms");
                foreach (string exTerm in this.ExcludedTerms)
                {
                    XmlNode exTermNode = XmlDataUtil.AddElement(ref xDoc, exTermRootNode, "ExcludedTerm");
                    XmlDataUtil.UpdateAttribute(ref xDoc, exTermNode, "Term", exTerm);
                }
            }

            return xNode;
        }
    }
}
